<template>
  <el-dialog
    v-model="dialogVisible"
    width="448"
    append-to-body
    :close-on-click-modal="false"
    :before-close="handleCancel"
  >
    <template #header>
      <div class="title flex align-items-end">
        <b style="font-size: 18px">{{ title }}</b>
        <span class="el-upload__tip ml-1">上传时请勿切换页面</span>
      </div>
    </template>
    <el-upload
      v-model:file-list="fileList"
      class="upload-dragger"
      drag
      :action="actionUrl"
      :on-progress="handleProgress"
      :auto-upload="autoUpload"
      :headers="headers"
      :multiple="multiple"
      :accept="accept"
      :on-change="handleChange"
      :before-upload="handleBeforeUpload"
    >
      <template #default>
        <div class="img flex-column justify-content-center align-items-center">
          <img
            src="https://bkcdn.riselinkedu.com/staticImages/resourceLibrary/upload_logo.png"
            alt=""
            class="mb-2"
            style="width: 64px; height: 64px"
          />
          <div class="el-upload__text flex-column">
            <span
              ><b>拖拽素材到这里，或</b><em><b>点此添加</b></em></span
            >
            <span
              v-if="uploadType === 'video'"
              style="font-size: 10px; color: #666666; margin-top: 2px"
            >
              （若文件过大，建议单次上传一个视频）
            </span>
          </div>
        </div>
      </template>
      <template #file="{ file }">
        <div class="upload-item flex">
          <div class="upload-item-image">
            <img
              v-if="(file as any).raw.type.includes('image')"
              :src="fileUrl"
              @click="handlePreview(file)"
            />
            <div v-if="file.status !== 'success'" class="upload-item-progress">
              <el-progress
                type="circle"
                :percentage="file.percentage || 0"
                :show-text="false"
                color="#513AA6"
                :stroke-width="12"
              />
            </div>
            <div
              v-if="file.status == 'success'"
              class="upload-delete"
              @click="handleDelete(file)"
            >
              <el-icon><Delete /></el-icon>
            </div>
          </div>
          <!-- 文件信息 -->
          <div class="upload-item-info">
            <div>{{ file.name }}</div>
            <div v-if="!(file as any)?.response?.data" class="upload-error">
              {{ (file as any)?.response?.msg }}
            </div>
          </div>
        </div>
      </template>
      <template v-if="showTip" #tip>
        <div class="el-upload__tip">
          <div v-if="accept.includes('image')">图片大小最大不超过15MB</div>
          <div v-else>文件大小最大不超过2G</div>
        </div>
      </template>
    </el-upload>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="handleConfirm">上传</el-button>
      </div>
    </template>
  </el-dialog>

  <!-- 图片预览组件 -->
  <teleport to="body">
    <el-image-viewer
      v-if="showViewer"
      :url-list="[previewUrl]"
      :hide-on-click-modal="true"
      class="image-viewer-highest"
      @close="showViewer = false"
    />
  </teleport>
</template>

<script setup lang="ts">
import { reportApi } from "@/api/report-api";
import { Delete } from "@element-plus/icons-vue";
import type { UploadFile, UploadFiles, UploadStatus } from "element-plus";
import { ElImageViewer, ElMessageBox } from "element-plus";
import { defineEmits, defineExpose, defineProps, ref, withDefaults } from "vue";

// 图片预览相关
const showViewer = ref(false);
const previewUrl = ref("");

// 使用 Element Plus 的类型
type CustomUploadFile = UploadFile & {
  percent?: number;
  status: UploadStatus | "error";
};

// 定义props
const props = withDefaults(
  defineProps<{
    autoUpload?: boolean;
    title?: string;
    multiple?: boolean;
    limit?: number;
    accept?: string;
    showTip?: boolean;
    uploadType?: string;
  }>(),
  {
    autoUpload: false, // 禁用自动上传
    title: "上传资源",
    multiple: true,
    limit: 4,
    accept: "image/png, image/jpeg, image/jpg",
    showTip: true,
    uploadType: ""
  }
);

// 基础数据
const dialogVisible = ref(false);
const fileList = ref<UploadFiles>([]);
const actionUrl = ref(""); // 阿里云上传地址，待实现
const headers = ref({}); // 上传请求头，待实现
// 文件url
const fileUrl = ref("");
// key
const resourceKey = ref("");

// 方法定义
const emit = defineEmits(["update:modelValue"]);

const handleShow = () => {
  dialogVisible.value = true;
};

const handleCancel = () => {
  fileList.value.length
    ? ElMessageBox.confirm(
        "取消后当前上传的文件将不会保存，是否确认取消？",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }
      )
        .then(() => {
          fileList.value = [];
          dialogVisible.value = false;
        })
        .catch(() => {})
    : (dialogVisible.value = false);
};

const handleDelete = (uploadFile: any) => {
  const index = fileList.value.findIndex(
    (item: any) => item.uid === uploadFile.uid
  );
  fileList.value.splice(index, 1);
};

// 文件上传进度处理
const handleProgress = (event: any, file: UploadFile) => {
  const index = fileList.value.findIndex(item => item.uid === file.uid);
  if (index !== -1) {
    const percent = Math.floor((event.loaded / event.total) * 100);
    if (fileList.value[index]) {
      fileList.value[index].percentage = percent;
      fileList.value[index].status = percent === 100 ? "success" : "uploading";
    }
  }
};

// 文件状态改变时的钩子
const handleChange = async (
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  if (uploadFile.status === "ready") {
    uploadFile.percentage = 0;

    try {
      // 获取文件类型（0：图片，1：其他类型）
      const fileType = uploadFile.raw.type.includes("image") ? 0 : 1;

      // 准备预签名URL的请求参数
      const params = {
        fileName: uploadFile.name,
        fileType: 2
      };

      // 获取预签名URL
      const presignedResponse = await reportApi.presignedApi(params);

      if (presignedResponse?.data?.presignedUrl) {
        // 更新上传状态
        uploadFile.status = "uploading";
        uploadFile.percentage = 0;

        try {
          // 第二步：使用fetch直接上传到预签名URL
          const uploadResponse = await fetch(
            presignedResponse?.data?.presignedUrl,
            {
              method: "PUT",
              body: uploadFile.raw,
              // 详细日志：设置Content-Type为上传文件的类型，如果没有则使用默认类型
              headers: {
                "Content-Type":
                  uploadFile.raw?.type || "application/octet-stream"
              }
            }
          );
          console.log("mujin uploadResponse :>> ", uploadResponse);
          if (!uploadResponse.ok) {
            throw new Error(
              `上传失败: ${uploadResponse.status} ${uploadResponse.statusText}`
            );
          } else {
            fileUrl.value = presignedResponse?.data?.fileAccessUrl;
            resourceKey.value = presignedResponse?.data?.objectKey;
            uploadFile.status = "success";
            uploadFile.percentage = 100;
            uploadFile.response = {
              data: presignedResponse.data.fileUrl,
              msg: "上传成功"
            };
          }
          console.log(
            "mujin uploadResponse :>> ",
            presignedResponse?.data?.fileAccessUrl
          );
        } catch (uploadError) {
          // uploadFile.status = "error";
          uploadFile.response = {
            msg: "文件上传失败"
          };
          ElMessageBox.alert("文件上传失败，请重试");
        }
      } else {
        throw new Error("获取预签名URL失败");
      }
    } catch (error) {
      console.error("文件上传失败:", error);
      // uploadFile.status = "error";
      uploadFile.response = {
        msg: "获取预签名URL失败"
      };
      ElMessageBox.alert("获取上传地址失败，请重试");
    }
  }
};

// 预览
const handlePreview = (file: any) => {
  if (file.raw.type.includes("image")) {
    previewUrl.value = fileUrl.value;
    showViewer.value = true;
  }
};
// 上传文件前的钩子
const handleBeforeUpload = (rawFile: File) => {
  // 文件大小检查（图片15MB，其他文件2GB）
  const isImage = rawFile.type.includes("image");
  const maxSize = isImage ? 15 * 1024 * 1024 : 2 * 1024 * 1024 * 1024;

  if (rawFile.size > maxSize) {
    ElMessageBox.alert(
      isImage ? "图片大小不能超过15MB" : "文件大小不能超过2GB"
    );
    return false;
  }

  // 文件类型检查
  if (
    props.accept &&
    !props.accept.split(",").some(type => {
      const cleanType = type.trim();
      // 处理mime类型 image/* 这种格式
      if (cleanType.endsWith("/*")) {
        const baseType = cleanType.slice(0, -2);
        return rawFile.type.startsWith(baseType);
      }
      return rawFile.type === cleanType;
    })
  ) {
    ElMessageBox.alert("文件类型不符合要求");
    return false;
  }

  // 文件数量检查
  if (fileList.value.length >= props.limit) {
    ElMessageBox.alert(`最多只能上传${props.limit}个文件`);
    return false;
  }

  return true;
};

const handleConfirm = () => {
  // 检查是否所有文件都上传成功
  const hasFailedUploads = fileList.value.some(
    file => file.status === "ready" || file.status === "uploading"
  );

  if (hasFailedUploads) {
    ElMessageBox.alert("存在上传失败或未完成的文件，请重试或删除失败文件");
    return;
  }

  // 所有文件都上传成功，发送文件列表并关闭对话框
  emit("update:modelValue", { resourceKey: resourceKey.value });
  dialogVisible.value = false;
};

// 暴露方法
defineExpose({
  handleShow
});
</script>

<style lang="scss" scoped>
:deep(.el-upload) {
  display: flex;
  justify-content: center;
}

// 确保图片预览组件在最高层级
:deep(.image-viewer-highest) {
  z-index: 9999 !important;
}

:deep(.el-image-viewer__wrapper) {
  z-index: 9999 !important;
}

:deep(.el-upload-dragger) {
  width: 400px;
  height: 146px;
  background: #f5f7fa;
  border-radius: 8px;
  border: 1px dashed #dcdfe6;
  padding-top: 24px;

  .upload-icon {
    font-size: 72px;
    margin-bottom: 6px;
  }
}

.upload-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  position: relative;
  cursor: pointer;

  &:hover {
    background-color: #f5f7fa;
  }

  .upload-item-image {
    width: 60px;
    height: 60px;
    border: 1px solid #dcdfe6;
    border-radius: 3px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    overflow: hidden;

    img {
      max-width: 100%;
      max-height: 100%;
    }

    .upload-delete {
      position: absolute;
      right: 0;
      top: 0;
      width: 20px;
      height: 22px;
      background: rgba(0, 0, 0, 0.7);
      color: #fff;
      border-radius: 4px 0 0 4px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 12px;
    }

    .upload-item-progress {
      position: absolute;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      display: flex;
      justify-content: center;
      align-items: center;

      :deep(.el-progress-circle) {
        width: 32px !important;
        height: 32px !important;
      }
    }
  }

  .upload-item-info {
    flex: 1;
    margin-left: 10px;
    font-size: 14px;

    .upload-error {
      color: #f56c6c;
      font-size: 12px;
      margin-top: 4px;
    }
  }
}
</style>
